package com.eduagent.xwqeduagent.controller;

import com.eduagent.xwqeduagent.api.OneSentenceReprint.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 声音复刻(一句话声音合成)统一控制器
 * 整合了鉴权、文本获取、训练任务创建和提交、查询训练状态以及音频合成等功能
 */
@RestController
@RequestMapping("/voice-replica")
public class VoiceReplicaController {

    @Autowired
    private AuthService authService;
    
    @Autowired
    private TrainTextService trainTextService;
    
    @Autowired
    private TrainTaskService trainTaskService;
    
    @Autowired
    private TrainAudioService trainAudioService;
    
    @Autowired
    private VoiceCloneService voiceCloneService;
    
    @Value("${xwqeduagent.audio.output-path:audio_output}")
    private String audioOutputPath;

    /**
     * 获取鉴权令牌
     * @return 返回鉴权令牌
     */
    @GetMapping("/auth/token")
    public ResponseEntity<Map<String, Object>> getToken() {
        try {
            String token = authService.getToken();
            
            Map<String, Object> result = new HashMap<>();
            result.put("code", 0);
            result.put("message", "获取令牌成功");
            result.put("token", token);
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", "获取令牌失败: " + e.getMessage());
            return ResponseEntity.status(500).body(result);
        }
    }
    
    /**
     * 获取训练文本列表
     * @param textId 文本ID
     * @return 返回训练文本列表
     */
    @GetMapping("/train/text")
    public ResponseEntity<Map<String, Object>> getTrainText(@RequestParam Long textId) {
        try {
            // 先获取token
            String token = authService.getToken();
            
            // 获取训练文本
            TrainTextService.TrainTextResponse response = trainTextService.getTrainText(token, textId);
            
            // 构建响应
            Map<String, Object> result = new HashMap<>();
            result.put("code", 0);
            result.put("message", "获取训练文本成功");
            result.put("data", response.getData());
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", "获取训练文本失败: " + e.getMessage());
            return ResponseEntity.status(500).body(result);
        }
    }
    
    /**
     * 创建训练任务
     * @param request 创建任务请求参数
     * @return 返回包含任务ID的响应
     */
    @PostMapping("/train/task")
    public ResponseEntity<Map<String, Object>> createTask(@RequestBody TrainTaskService.CreateTaskRequest request) {
        try {
            // 验证必填参数
            if (request.getResourceType() == null) {
                request.setResourceType(12); // 默认设置为一句话合成
            }
            
            // 先获取token
            String token = authService.getToken();
            
            // 创建训练任务
            TrainTaskService.CreateTaskResponse response = trainTaskService.createTask(token, request);
            
            // 构建响应
            Map<String, Object> result = new HashMap<>();
            result.put("code", 0);
            result.put("message", "创建训练任务成功");
            result.put("taskId", response.getData());
            return ResponseEntity.ok(result);
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", "创建训练任务失败: " + e.getMessage());
            return ResponseEntity.status(500).body(result);
        }
    }
    
    /**
     * 提交训练任务
     * @param taskId 训练任务ID
     * @return 返回操作结果
     */
    @PostMapping("/train/task/submit")
    public ResponseEntity<Map<String, Object>> submitTask(@RequestParam String taskId) {
        try {
            // 验证必填参数
            if (taskId == null || taskId.isEmpty()) {
                return ResponseEntity.badRequest().body(
                    Map.of("code", -1, "message", "训练任务ID不能为空")
                );
            }
            
            // 先获取token
            String token = authService.getToken();
            
            // 提交训练任务
            TrainTaskService.SubmitTaskResponse response = trainTaskService.submitTask(token, taskId);
            
            // 构建响应
            Map<String, Object> result = new HashMap<>();
            result.put("code", 0);
            result.put("message", "提交训练任务成功");
            return ResponseEntity.ok(result);
        } catch (IllegalArgumentException e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", e.getMessage());
            return ResponseEntity.badRequest().body(result);
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", "提交训练任务失败: " + e.getMessage());
            return ResponseEntity.status(500).body(result);
        }
    }
    
    /**
     * 上传音频文件并提交训练
     * @param file 音频文件
     * @param taskId 任务ID
     * @param textId 文本ID
     * @param textSegId 文本段落ID
     * @return 返回上传结果
     */
    @PostMapping("/train/audio/upload")
    public ResponseEntity<Map<String, Object>> uploadAudioFile(
            @RequestParam("file") MultipartFile file,
            @RequestParam String taskId,
            @RequestParam Long textId,
            @RequestParam Long textSegId) {
        try {
            // 验证必填参数
            if (file == null || file.isEmpty()) {
                return ResponseEntity.badRequest().body(
                    Map.of("code", -1, "message", "音频文件不能为空")
                );
            }
            
            if (taskId == null || taskId.isEmpty()) {
                return ResponseEntity.badRequest().body(
                    Map.of("code", -1, "message", "任务ID不能为空")
                );
            }
            
            // 先获取token
            String token = authService.getToken();
            
            // 创建请求对象
            TrainAudioService.SubmitWithAudioRequest request = new TrainAudioService.SubmitWithAudioRequest();
            request.setAudioFile(file);
            request.setTaskId(taskId);
            request.setTextId(textId);
            request.setTextSegId(textSegId);
            
            // 上传音频并提交训练
            TrainAudioService.SubmitWithAudioResponse response = 
                trainAudioService.submitWithAudio(token, request);
            
            // 构建响应
            Map<String, Object> result = new HashMap<>();
            result.put("code", 0);
            result.put("message", "上传音频并提交训练成功");
            return ResponseEntity.ok(result);
        } catch (IllegalArgumentException e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", e.getMessage());
            return ResponseEntity.badRequest().body(result);
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", "上传音频文件失败: " + e.getMessage());
            return ResponseEntity.status(500).body(result);
        }
    }
    
    /**
     * 添加音频URL
     * @param request 添加音频URL请求
     * @return 返回添加结果
     */
    @PostMapping("/train/audio/add-url")
    public ResponseEntity<Map<String, Object>> addAudioUrl(@RequestBody TrainAudioService.AddAudioRequest request) {
        try {
            // 验证必填参数
            if (request.getTaskId() == null || request.getTaskId().isEmpty()) {
                return ResponseEntity.badRequest().body(
                    Map.of("code", -1, "message", "任务ID不能为空")
                );
            }
            if (request.getAudioUrl() == null || request.getAudioUrl().isEmpty()) {
                return ResponseEntity.badRequest().body(
                    Map.of("code", -1, "message", "音频URL不能为空")
                );
            }
            
            // 先获取token
            String token = authService.getToken();
            
            // 添加音频URL
            TrainAudioService.AddAudioResponse response = trainAudioService.addAudio(token, request);
            
            // 构建响应
            Map<String, Object> result = new HashMap<>();
            result.put("code", 0);
            result.put("message", "添加音频URL成功");
            return ResponseEntity.ok(result);
        } catch (IllegalArgumentException e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", e.getMessage());
            return ResponseEntity.badRequest().body(result);
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", "添加音频URL失败: " + e.getMessage());
            return ResponseEntity.status(500).body(result);
        }
    }
    
    /**
     * 查询训练任务状态
     * @param taskId 训练任务ID
     * @return 返回包含任务状态的响应
     */
    @GetMapping("/train/task/status")
    public ResponseEntity<Map<String, Object>> getTaskStatus(@RequestParam String taskId) {
        try {
            // 验证必填参数
            if (taskId == null || taskId.isEmpty()) {
                return ResponseEntity.badRequest().body(
                    Map.of("code", -1, "message", "训练任务ID不能为空")
                );
            }
            
            // 先获取token
            String token = authService.getToken();
            
            // 查询训练任务状态
            TrainTaskService.TaskResultResponse response = trainTaskService.getTaskResult(token, taskId);
            
            // 构建响应
            Map<String, Object> result = new HashMap<>();
            result.put("code", response.getCode());
            result.put("message", response.getDesc());
            
            // 如果查询成功，添加任务状态信息
            if (response.getCode() == 0 && response.getData() != null) {
                Map<String, Object> taskInfo = new HashMap<>();
                TrainTaskService.TaskResultResponse.TaskResultData data = response.getData();
                
                taskInfo.put("taskName", data.getTaskName());
                taskInfo.put("resourceName", data.getResourceName());
                taskInfo.put("sex", data.getSex());
                taskInfo.put("ageGroup", data.getAgeGroup());
                taskInfo.put("trainVid", data.getTrainVid());
                taskInfo.put("assetId", data.getAssetId());
                taskInfo.put("trainId", data.getTrainId());
                taskInfo.put("appId", data.getAppId());
                taskInfo.put("trainStatus", data.getTrainStatus());
                taskInfo.put("trainStatusDesc", getTrainStatusDesc(data.getTrainStatus()));
                taskInfo.put("failedDesc", data.getFailedDesc());
                
                result.put("data", taskInfo);
            }
            
            return ResponseEntity.ok(result);
        } catch (IllegalArgumentException e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", e.getMessage());
            return ResponseEntity.badRequest().body(result);
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", "查询训练任务状态失败: " + e.getMessage());
            return ResponseEntity.status(500).body(result);
        }
    }
    
    /**
     * 音频合成接口
     * @param request 合成请求参数
     * @return 返回包含合成结果的响应
     */
    @PostMapping("/synthesize")
    public ResponseEntity<Map<String, Object>> synthesizeAudio(@RequestBody VoiceCloneService.CloneRequest request) {
        try {
            // 验证必填参数
            if (request.getResId() == null || request.getResId().isEmpty()) {
                return ResponseEntity.badRequest().body(
                    Map.of("code", -1, "message", "音色ID不能为空")
                );
            }
            if (request.getText() == null || request.getText().isEmpty()) {
                return ResponseEntity.badRequest().body(
                    Map.of("code", -1, "message", "合成文本不能为空")
                );
            }
            
            // 确保输出目录存在
            ensureOutputDirectoryExists();
            
            // 生成输出文件名
            String fileName = "voice_" + UUID.randomUUID().toString().replace("-", "") + ".mp3";
            String outputFilePath = Paths.get(audioOutputPath, fileName).toString();
            
            // 执行音频合成
            VoiceCloneService.CloneResult result = voiceCloneService.synthesizeAudio(request, outputFilePath);
            
            // 构建响应
            Map<String, Object> response = new HashMap<>();
            response.put("code", result.isSuccess() ? 0 : -1);
            response.put("message", result.getMessage());
            
            if (result.isSuccess()) {
                Map<String, Object> data = new HashMap<>();
                data.put("sid", result.getSid());
                data.put("audioFile", fileName);
                data.put("audioUrl", "/api/voice-replica/audio/" + fileName);
                
                // 如果有音素标注，添加到响应中
                if (result.getPyBufText() != null && !result.getPyBufText().isEmpty()) {
                    data.put("pyBufText", result.getPyBufText());
                }
                
                response.put("data", data);
            }
            
            return ResponseEntity.ok(response);
        } catch (IllegalArgumentException e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", e.getMessage());
            return ResponseEntity.badRequest().body(result);
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", "音频合成失败: " + e.getMessage());
            return ResponseEntity.status(500).body(result);
        }
    }
    
    /**
     * 获取合成的音频文件
     * @param fileName 文件名
     * @return 音频文件
     */
    @GetMapping("/audio/{fileName}")
    public ResponseEntity<?> getAudioFile(@PathVariable String fileName) {
        try {
            Path filePath = Paths.get(audioOutputPath, fileName);
            File file = filePath.toFile();
            
            if (!file.exists()) {
                return ResponseEntity.notFound().build();
            }
            
            return ResponseEntity.ok()
                    .header("Content-Type", "audio/mpeg")
                    .header("Content-Disposition", "attachment; filename=\"" + fileName + "\"")
                    .body(Files.readAllBytes(filePath));
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("code", -1);
            result.put("message", "获取音频文件失败: " + e.getMessage());
            return ResponseEntity.status(500).body(result);
        }
    }
    
    /**
     * 获取训练状态描述
     * @param trainStatus 训练状态码
     * @return 训练状态描述
     */
    private String getTrainStatusDesc(int trainStatus) {
        switch (trainStatus) {
            case -1:
                return "训练中";
            case 0:
                return "训练失败";
            case 1:
                return "训练成功";
            case 2:
                return "草稿";
            default:
                return "未知状态";
        }
    }
    
    /**
     * 确保输出目录存在
     */
    private void ensureOutputDirectoryExists() {
        File directory = new File(audioOutputPath);
        if (!directory.exists()) {
            directory.mkdirs();
        }
    }
} 